/*
 *  UVCCamera
 *  library and sample to access to UVC web camera on non-rooted Android device
 *
 * Copyright (c) 2014-2017 saki t_saki@serenegiant.com
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 *  All files in the folder are under this Apache License, Version 2.0.
 *  Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder
 *  may have a different license, see the respective files.
 */

package com.sunny.sunnyUVCCam;

import android.Manifest;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.hardware.usb.UsbDevice;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.Spinner;
import android.widget.Toast;
import android.widget.ToggleButton;

import com.serenegiant.common.BaseActivity;
import com.serenegiant.usb.CameraDialog;
import com.serenegiant.usb.USBMonitor;
import com.serenegiant.usb.USBMonitor.OnDeviceConnectListener;
import com.serenegiant.usb.USBMonitor.UsbControlBlock;
import com.serenegiant.usb.UVCCamera;

public class MainActivity extends BaseActivity implements CameraDialog.CameraDialogParent {
	private static final boolean DEBUG = true;	// TODO set false when production
	private static final String TAG = "MainActivity";

    private final Object mSync = new Object();
    // for accessing USB and USB camera
    private USBMonitor mUSBMonitor;
	private UVCCamera mUVCCamera;
	private SurfaceView mUVCCameraView;
	// for open&start / stop&close camera preview
	private ImageButton mCameraButton;
	private Button mCaptureButton;
	private ToggleButton mToggleButton;
	private Surface mPreviewSurface;
	private boolean isActive, isPreview;
	private int mPreviewMode = UVCCamera.FRAME_FORMAT_YUYV;
	private int mPreviewWidth = 640;
	private int mPreviewHeight = 480;

	private final static String[] texts = {"640x480", "224x1730", "224x1038", "480x182"};
	private final static String[] capture_option = { "0", "1", "5", "10", "20"};
	private final static int[] capture_value = { 0, 1, 5, 10, 20};
	private final static int[] values = {1, 2, 3};
	private int mCaptureIndex = 0;
	private Spinner spinner;
	private ArrayAdapter<String> adapter;

	@Override
	protected void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// When the compile and target version is higher than 22, please request the following permissions at runtime to ensure the SDK work well.
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
			ActivityCompat.requestPermissions(this,
					new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,
					}
					, 1);
		}
		setContentView(R.layout.activity_main);
		mCameraButton = (ImageButton)findViewById(R.id.camera_button);
		mCameraButton.setOnClickListener(mOnClickListener);

		mToggleButton = (ToggleButton)findViewById(R.id.toggle_camera_button) ;
//		mToggleButton.setEnabled(false);

		mCaptureButton = (Button)findViewById(R.id.capture_button);
		mCaptureButton.setOnClickListener(mOnClickListener);

		mUVCCameraView = (SurfaceView)findViewById(R.id.camera_surface_view);
		mUVCCameraView.getHolder().addCallback(mSurfaceViewCallback);
		mUVCCameraView.setKeepScreenOn(true);

		spinner = (Spinner)findViewById(R.id.spinner2);
		adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, texts);
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		spinner.setAdapter(adapter);
		spinner.setOnItemSelectedListener(new SpinnerSelectedListener());
		spinner.setSelection(2);
		spinner.setVisibility(View.VISIBLE);

		mUSBMonitor = new USBMonitor(this, mOnDeviceConnectListener);
	}

	public void touchCameraToggleClick(View view) {

		if (((ToggleButton) view).isChecked()) { //yuv
			mPreviewMode = UVCCamera.FRAME_FORMAT_YUYV;
		} else {
			mPreviewMode = UVCCamera.FRAME_FORMAT_MJPEG;
		}
	}

	public void setPreviewSize(int size){
		switch (size){
			case 0:
				mPreviewWidth = 640;
				mPreviewHeight = 480;
				break;
			case 1:
				mPreviewWidth = 224;
				mPreviewHeight = 1730;
				break;
			case 2:
				mPreviewWidth = 224;
				mPreviewHeight = 1038;
				break;
			case 3:
				mPreviewWidth = 480;
				mPreviewHeight = 182;
				break;
			default:
				mPreviewWidth = 640;
				mPreviewHeight = 480;
				break;
		}
	}

	public class SpinnerSelectedListener implements AdapterView.OnItemSelectedListener {

		public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) {
        Toast.makeText(parent.getContext(),
                "OnItemSelectedListener : " + parent.getItemAtPosition(pos).toString(),
                Toast.LENGTH_SHORT).show();
			setPreviewSize(pos);
		}

		@Override
		public void onNothingSelected(AdapterView<?> arg0) {
			// TODO Auto-generated method stub
		}

	}

	@Override
	protected void onStart() {
		super.onStart();
		if (DEBUG) Log.v(TAG, "onStart:");
		synchronized (mSync) {
			if (mUSBMonitor != null) {
				mUSBMonitor.register();
			}
		}
	}

	@Override
	protected void onStop() {
		if (DEBUG) Log.v(TAG, "onStop:");
		synchronized (mSync) {
			if (mUSBMonitor != null) {
				mUSBMonitor.unregister();
			}
		}
		super.onStop();
	}

	@Override
	protected void onDestroy() {
		if (DEBUG) Log.v(TAG, "onDestroy:");
		synchronized (mSync) {
			isActive = isPreview = false;
			if (mUVCCamera != null) {
				mUVCCamera.destroy();
				mUVCCamera = null;
			}
			if (mUSBMonitor != null) {
				mUSBMonitor.destroy();
				mUSBMonitor = null;
			}
		}
		mUVCCameraView = null;
		mCameraButton = null;
		super.onDestroy();
	}

	private void showDialog(){
		AlertDialog.Builder builder=new AlertDialog.Builder(this);
		builder.setTitle("选择抓图数量");
//		builder.setIcon(R.drawable.ic_launcher);
		builder.setSingleChoiceItems(capture_option,mCaptureIndex,new DialogsingleClickListener());
		AlertDialog dialog=builder.create();
		dialog.show();
	}

	class DialogsingleClickListener implements DialogInterface.OnClickListener{

		@Override
		public void onClick(DialogInterface dialog, int which) {
			// 判断 单选按钮
			Toast.makeText(MainActivity.this,"连续抓图" + capture_option[which] +"张",Toast.LENGTH_SHORT).show();
//			tv_result.setText(items[which]);
			mCaptureIndex = which;
			if(isPreview){
				mUVCCamera.setCaptureCount(capture_value[mCaptureIndex]);
			}
			dialog.dismiss();
		}

	}

	private final OnClickListener mOnClickListener = new OnClickListener() {
		@Override
		public void onClick(final View view) {
			switch (view.getId()) {
				case R.id.capture_button:
					showDialog();
//					mUVCCamera.setCaptureCount(10);

					break;
				case R.id.camera_button:
					if (mUVCCamera == null) {
						// XXX calling CameraDialog.showDialog is necessary at only first time(only when app has no permission).
						CameraDialog.showDialog(MainActivity.this);
					} else {
						synchronized (mSync) {
							mUVCCamera.destroy();
							mUVCCamera = null;
							isActive = isPreview = false;
							mToggleButton.setEnabled(true);
						}
					}
					break;
			}
		}
	};

	private final OnDeviceConnectListener mOnDeviceConnectListener = new OnDeviceConnectListener() {
		@Override
		public void onAttach(final UsbDevice device) {
			if (DEBUG) Log.v(TAG, "onAttach:");
			Toast.makeText(MainActivity.this, "USB_DEVICE_ATTACHED", Toast.LENGTH_SHORT).show();
		}

		@Override
		public void onConnect(final UsbDevice device, final UsbControlBlock ctrlBlock, final boolean createNew) {
			if (DEBUG) Log.v(TAG, "onConnect:");
			synchronized (mSync) {
				if (mUVCCamera != null) {
					mUVCCamera.destroy();
				}
				isActive = isPreview = false;
			}
			queueEvent(new Runnable() {
				@Override
				public void run() {
					synchronized (mSync) {
						final UVCCamera camera = new UVCCamera();
						camera.open(ctrlBlock);
						camera.setCaptureCount(capture_value[mCaptureIndex]);
						if (DEBUG) Log.i(TAG, "supportedSize:" + camera.getSupportedSize());
						try {
							camera.setPreviewSize(mPreviewWidth, mPreviewHeight, mPreviewMode);
						} catch (final IllegalArgumentException e) {
							try {
								// fallback to YUV mode
								camera.setPreviewSize(mPreviewWidth, mPreviewHeight, mPreviewMode);
							} catch (final IllegalArgumentException e1) {
								camera.destroy();
								return;
							}
						}
						mPreviewSurface = mUVCCameraView.getHolder().getSurface();
						if (mPreviewSurface != null) {
							isActive = true;
							camera.setPreviewDisplay(mPreviewSurface);
							camera.startPreview();
							isPreview = true;
						}
						synchronized (mSync) {
							mUVCCamera = camera;
						}

						//zhudm
						runOnUiThread(new Runnable() {
							@Override
							public void run() {
								mToggleButton.setEnabled(false);
							}
						}, 0);
					}
				}
			}, 0);
		}

		@Override
		public void onDisconnect(final UsbDevice device, final UsbControlBlock ctrlBlock) {
			if (DEBUG) Log.v(TAG, "onDisconnect:");
			mToggleButton.setEnabled(false);
			// XXX you should check whether the comming device equal to camera device that currently using
			queueEvent(new Runnable() {
				@Override
				public void run() {
					synchronized (mSync) {
						if (mUVCCamera != null) {
							mUVCCamera.close();
							if (mPreviewSurface != null) {
								mPreviewSurface.release();
								mPreviewSurface = null;
							}
							isActive = isPreview = false;

						}
					}
				}
			}, 0);
		}

		@Override
		public void onDettach(final UsbDevice device) {
			if (DEBUG) Log.v(TAG, "onDettach:");
			Toast.makeText(MainActivity.this, "USB_DEVICE_DETACHED", Toast.LENGTH_SHORT).show();
		}

		@Override
		public void onCancel(final UsbDevice device) {
		}
	};

	/**
	 * to access from CameraDialog
	 * @return
	 */
	@Override
	public USBMonitor getUSBMonitor() {
		return mUSBMonitor;
	}

	@Override
	public void onDialogResult(boolean canceled) {
		if (canceled) {
			runOnUiThread(new Runnable() {
				@Override
				public void run() {
					// FIXME
				}
			}, 0);
		}
	}

	private final SurfaceHolder.Callback mSurfaceViewCallback = new SurfaceHolder.Callback() {
		@Override
		public void surfaceCreated(final SurfaceHolder holder) {
			if (DEBUG) Log.v(TAG, "surfaceCreated:");
		}

		@Override
		public void surfaceChanged(final SurfaceHolder holder, final int format, final int width, final int height) {
			if ((width == 0) || (height == 0)) return;
			if (DEBUG) Log.v(TAG, "surfaceChanged:");
			mPreviewSurface = holder.getSurface();
			synchronized (mSync) {
				if (isActive && !isPreview && (mUVCCamera != null)) {
					mUVCCamera.setPreviewDisplay(mPreviewSurface);
					mUVCCamera.startPreview();
					isPreview = true;
					mToggleButton.setEnabled(true);
				}
			}
		}

		@Override
		public void surfaceDestroyed(final SurfaceHolder holder) {
			if (DEBUG) Log.v(TAG, "surfaceDestroyed:");
			synchronized (mSync) {
				if (mUVCCamera != null) {
					mUVCCamera.stopPreview();
				}
				isPreview = false;
			}
			mPreviewSurface = null;
		}
	};
}
